#include <bits/stdc++.h>
using namespace std;

/*
2844. 生成特殊数字的最少操作
已解答
中等
相关标签
相关企业
提示
给你一个下标从 0 开始的字符串 num ，表示一个非负整数。

在一次操作中，您可以选择 num 的任意一位数字并将其删除。请注意，如果你删除 num 中的所有数字，则 num 变为 0。

返回最少需要多少次操作可以使 num 变成特殊数字。

如果整数 x 能被 25 整除，则该整数 x 被认为是特殊数字。

 

 

示例 1：

输入：num = "2245047"
输出：2
解释：删除数字 num[5] 和 num[6] ，得到数字 "22450" ，可以被 25 整除。
可以证明要使数字变成特殊数字，最少需要删除 2 位数字。
示例 2：

输入：num = "2908305"
输出：3
解释：删除 num[3]、num[4] 和 num[6] ，得到数字 "2900" ，可以被 25 整除。
可以证明要使数字变成特殊数字，最少需要删除 3 位数字。
示例 3：

输入：num = "10"
输出：1
解释：删除 num[0] ，得到数字 "0" ，可以被 25 整除。
可以证明要使数字变成特殊数字，最少需要删除 1 位数字。
 

提示

1 <= num.length <= 100
num 仅由数字 '0' 到 '9' 组成
num 不含任何前导零
*/

// 法一
class Solution
{
public:
	int minimumOperations(string num)
	{
		int n = num.size();
		int ans = n; // 初始化为全删的最坏情况
		bool has_zero = false;

		// 检查是否存在0，至少可以保留一个0的情况
		for (char c : num)
		{
			if (c == '0')
			{
				has_zero = true;
				ans = n - 1; // 删除其他字符保留一个0
				break;
			}
		}

		// 定义四种可能的组合：00、25、50、75
		vector<pair<char, char>> patterns = {{'0', '0'}, {'2', '5'}, {'5', '0'}, {'7', '5'}};
		for (auto [x, y] : patterns)
		{
			int last_y = -1;
			// 从后往前找最后一个y的位置
			for (int i = n - 1; i >= 0; --i)
			{
				if (num[i] == y)
				{
					last_y = i;
					break;
				}
			}
			if (last_y == -1)
				continue;

			int last_x = -1;
			// 在last_y左侧找最后一个x的位置
			for (int j = last_y - 1; j >= 0; --j)
			{
				if (num[j] == x)
				{
					last_x = j;
					break;
				}
			}
			if (last_x == -1)
				continue;

			// 计算需要删除的字符数：后面的字符数（n - last_y - 1） + 前面的字符数（last_y - last_x - 1）
			int deletions = (n - last_y - 1) + (last_y - last_x - 1);
			ans = min(ans, deletions);
		}

		return ans;
	}
};

// 法二
class Solution
{
public:
	int minimumOperations(string num)
	{
		int n = num.size();
		int ans = num.find('0') != string::npos ? n - 1 : n; // 处理单个0的情况[7](@ref)
		vector<pair<char, char>> patterns = {
			{'0', '0'}, {'2', '5'}, {'5', '0'}, {'7', '5'}};

		for (auto [x, y] : patterns)
		{
			int last_y = -1;
			// 从后往前找y的最后一个位置
			for (int i = n - 1; i >= 0; --i)
			{
				if (num[i] == y)
				{
					last_y = i;
					break;
				}
			}
			if (last_y == -1)
				continue;

			int last_x = -1;
			// 在last_y左侧找x的最后一个位置
			for (int j = last_y - 1; j >= 0; --j)
			{
				if (num[j] == x)
				{
					last_x = j;
					break;
				}
			}
			if (last_x == -1)
				continue;

			ans = min(ans, (n - last_y - 1) + (last_y - last_x - 1)); // 正确计算删除次数[7](@ref)
		}
		return ans;
	}
};